" Vim filetype plugin
" Language: MOG
" Maintainer: littlelot

" Only do this when not done yet for this buffer
if exists("b:did_ftplugin")
  finish
endif

unlet! b:did_ftplugin

if !exists('g:littlelot_mog_host')
  let g:littlelot_mog_host = 'localhost'
endif

if !exists('g:littlelot_mog_port')
  let g:littlelot_mog_port = '27017'
endif

if !exists('g:littlelot_mog_db')
  let g:littlelot_mog_db = 'test'
endif

if !exists('g:littlelot_mog_run_file')
  let g:littlelot_mog_run_file = tempname()
endif

let s:title = '-MongoDB-'

let s:zoom_in = 0
let s:keymap = {}

let s:help_open = 0
let s:help_text_short = [
            \ '" Press <F1> for help',
            \ '',
            \ ]
let s:help_text = s:help_text_short

let s:last_record_line = 0
let s:last_record_col = 0

" function! s:appendContent(content) {{{
function! s:appendContent(content)
  try
    call append(line('.'), split(a:content, '\n'))
    silent exec 'normal dd'
  catch /.*/
  endtry
  return ''
endfunction
" }}}

" 生成私有配置
" function exmog#LittlelotMongoDBGenConfig() {{{
function exmog#LittlelotMongoDBGenConfig()
  let s = "/* Littlelot MongoDB IDE */\n
\\n
\/* Littlelot MongoDB IDE Config\n
\@Host ".g:littlelot_mog_host."\n
\@Port ".g:littlelot_mog_port."\n
\@DataBase ".g:littlelot_mog_db."\n
\Littlelot MongoDB IDE Config */"
  return s:appendContent(s)
endfunction
" }}}

" 生成计算执行时间代码
" function exmog#LittlelotMongoDBGenTime() {{{
function exmog#LittlelotMongoDBGenTime()
let s = "/* 记录起始时间 */\n
\var currentTime = new Date().getTime()\n
\\n
\/* 这里输入你想要运行的代码... */\n
\\n
\/* 输出执行时间 */\n
\print(\"{ \\\"执行时间(秒)\\\" : \" + (new Date().getTime() - currentTime) / 1000 + \" }\")"
  return s:appendContent(s)
endfunction
" }}}

" 创建空文件自动生成模板
" function exmog#LittlelotMongoDBAutoGen() {{{
function exmog#LittlelotMongoDBAutoGen()
  let lastLineNo = line('$')
  if lastLineNo != 1 || len(getline(lastLineNo)) != 0
    return
  endif

  call exmog#LittlelotMongoDBGenConfig()
  silent exec "normal Go"
  silent exec "normal o"
  call exmog#LittlelotMongoDBGenTime()
endfunction
" }}}

" 根据内容给全局配置变量赋值
" function! s:assignConfig(config) {{{
function! s:assignConfig(config)
  try
    let [name, value] = split(a:config)
  catch /.*/
    return
  endtry

  if name == "@Host"
    let g:littlelot_mog_host = value
  elseif name == "@Port"
    let g:littlelot_mog_port = value
  elseif name == "@Database"
    let g:littlelot_mog_db = value
  endif
endfunction
" }}}

" 解析本文私有配置
" function! s:parseConfig() {{{
function! s:parseConfig()
  let re = '\ *littlelot\ *mongodb\ *ide\ *config\ *'
  let config = []

  let oline = line(".")
  let ocol = col(".")

  " if type(a:content) == 3
    " let start = match(a:content, '\c\/\*'.re)
    " let end = match(a:content, '\c'.re.'\*\/')
    " if start != -1 && end != -1
      " let config = a:content[start + 1 : end - 1]
      " unlet a:content[start : end]
    " endif
  " else
    " silent call cursor(1,1)
    " let start = search('\/\*'.re, 'n') + 1
    " let end = search(re.'\*\/', 'n') - 1
    " let config = getline(start, end)
  " endif

  silent call cursor(1,1)
  let start = search('\/\*'.re, 'n') + 1
  let end = search(re.'\*\/', 'n') - 1

  if start > 1 && end >= start
    let config = getline(start, end)
  else
    let config = []
  endif

  for x in config
    call s:assignConfig(x)
  endfor

  silent call cursor(oline, ocol)
endfunction
" }}}

" 清除列表中空行和SQL注释行
" function! s:clearComment(content_list) {{{
function! s:clearComment(content_list)
  let newlist = []
  for s in a:content_list
    if strlen(s) > 0 && match(s, '^/\*.*\|^@.*\|.*\*/$') == -1
      call add(newlist, s)
    endif
  endfor
  return newlist
endfunction
" }}}

" 解析配置执行mongo命令并且分割窗口显示
" function exmog#LittlelotMongoDBCmdView(isVisual) {{{
function exmog#LittlelotMongoDBCmdView(isVisual) range
  call s:parseConfig()

  if a:isVisual
      let content_list = [ "var currentTime = new Date().getTime()" ] + exmog#GetVisualSelection(a:firstline, a:lastline)
                  \ + [ "print(\"{ \\\"执行时间(秒)\\\" : \" + (new Date().getTime() - currentTime) / 1000 + \" }\")" ]
  else
      let content_list = s:clearComment( getline(1, line("$")) )
  endif

  silent call writefile(content_list, g:littlelot_mog_run_file)

  let cmd = "mongo --quiet mongodb://" . g:littlelot_mog_host . ":" . g:littlelot_mog_port . "/" . g:littlelot_mog_db
  let cmd .= " < " . g:littlelot_mog_run_file

  let result = system(cmd)

  call exmog#open_window()

  setlocal modifiable
  " clear contents
  silent exec '1,$d _'
  silent call append( 0, split(result, "\n") )
  silent exec 'normal! dd'
  silent exec 'normal! zb'
  silent set foldlevel=1
  setlocal nomodifiable

  call ex#window#goto_edit_window()
endfunction
" }}}

" function exmog#bind_mappings {{{
function exmog#bind_mappings()
    call ex#keymap#bind( s:keymap )
endfunction
" }}}

" function exmog#register_hotkey {{{
function exmog#register_hotkey( priority, local, key, action, desc )
    call ex#keymap#register( s:keymap, a:priority, a:local, a:key, a:action, a:desc )
endfunction
" }}}

" function s:update_help_text {{{
function s:update_help_text()
    if s:help_open
        let s:help_text = ex#keymap#helptext(s:keymap)
    else
        let s:help_text = s:help_text_short
    endif
endfunction
" }}}

" function exmog#toggle_help() {{{
function exmog#toggle_help()
    if !g:ex_mog_enable_help
        return
    endif

    let s:help_open = !s:help_open
    silent exec '1,' . len(s:help_text) . 'd _'
    call s:update_help_text()
    silent call append ( 0, s:help_text )
    silent exec 'normal! dd'
    silent keepjumps normal! gg
    call ex#hl#clear_confirm()
endfunction
" }}}

" function exmog#init_buffer {{{
function exmog#init_buffer()
    set filetype=json
    augroup exmog
        au! BufWinLeave <buffer> call <SID>on_close()
    augroup END
endfunction
" }}}

" function s:on_close() {{{
function s:on_close()
    let s:zoom_in = 0
    let s:help_open = 0
    let s:last_record_line = line('.')
    let s:last_record_col = col('.')

    " go back to edit buffer
    call ex#window#goto_edit_window()
endfunction
" }}}

" function exmog#open_window() {{{
function exmog#open_window()
    let winnr = winnr()
    if ex#window#check_if_autoclose(winnr)
        call ex#window#close(winnr)
    endif
    call ex#window#goto_edit_window()

    " 关闭冲突的插件窗口
    let winnr = bufwinnr(s:title)
    let sqlwinnr = bufwinnr("-MySQL-")
    let qfwinnr = bufwinnr("-QFix-")
    let jrwinnr = bufwinnr("-JavaSR-")
    let undotreewinnr = bufwinnr("undotree_0")
    let diffpanelwinnr = bufwinnr("diffpanel_0")

    if sqlwinnr != -1
        call ex#window#close(sqlwinnr)
    endif
    if qfwinnr != -1
        call ex#window#close(qfwinnr)
    endif
    if jrwinnr != -1
        call ex#window#close(jrwinnr)
    endif
    if undotreewinnr != -1 && diffpanelwinnr != -1 && exists ( ':UndotreeHide' )
        silent exec "UndotreeHide"
    endif

    if winnr == -1
        call ex#window#open(
                    \ s:title,
                    \ g:ex_mog_winsize,
                    \ g:ex_mog_winpos,
                    \ 1,
                    \ 1,
                    \ function('exmog#init_buffer')
                    \ )
    else
        exe winnr . 'wincmd w'
    endif

    if !s:last_record_line && !s:last_record_col
        silent execute 'normal! G'
    else
        silent call cursor(s:last_record_line, s:last_record_col)
    endif
endfunction
" }}}

" function exmog#toggle_window {{{
function exmog#toggle_window()
    let result = exmog#close_window()
    if result == 0
        call exmog#open_window()
    endif
endfunction
" }}}

" function exmog#close_window {{{
function exmog#close_window()
    let winnr = bufwinnr(s:title)
    if winnr != -1
        call ex#window#close(winnr)
        return 1
    endif
    return 0
endfunction
" }}}

" function exmog#toggle_zoom {{{
function exmog#toggle_zoom()
    let winnr = bufwinnr(s:title)
    if winnr != -1
        if s:zoom_in == 0
            let s:zoom_in = 1
            call ex#window#resize( winnr, g:ex_mog_winpos, g:ex_mog_winsize_zoom )
        else
            let s:zoom_in = 0
            call ex#window#resize( winnr, g:ex_mog_winpos, g:ex_mog_winsize )
        endif
    endif
endfunction
" }}}

" 返回可视模式下已选中内容(必须是可视模式下调用)
" function exmog#GetVisualSelection() {{{
function exmog#GetVisualSelection(startline, endline)
  let col1 = getpos("'<")[2]
  let col2 = getpos("'>")[2]
  let lines = getline(a:startline, a:endline)
  let lines[-1] = lines[-1][:col2 - (&selection == 'inclusive' ? 1 : 2)]
  let lines[0] = lines[0][col1 - 1:]
  return lines
endfunction
" }}}

" vim:ts=4:sw=4:sts=4 et fdm=marker:
